﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Reflection;
using System.ComponentModel;

namespace Douban.Core.Interop
{
    public delegate int WindowsHookProc(int code, int wParam, IntPtr lParam);

    public static class WindowsHookHelper
    {
        [DllImport("user32.dll")]
        private static extern IntPtr SetWindowsHookEx(
            WindowsHookTypes idHook,
            WindowsHookProc lpfn,
            IntPtr hInstance,
            int dwThreadId);

        [DllImport("user32.dll")]
        private static extern IntPtr UnhookWindowsHookEx(IntPtr hhk);

        [DllImport("user32.dll")]
        private static extern int CallNextHookEx(IntPtr hhk, int nCode, int wParam, IntPtr lParam);

        public static IntPtr RegisterWindowsHook(WindowsHookTypes hookType, WindowsHookProc windowsHookHandler)
        {
            IntPtr hHook = SetWindowsHookEx(hookType, windowsHookHandler, 
                Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]), 0);

            if (hHook.ToInt32() != 0) return hHook;

            throw new Win32Exception(Marshal.GetLastWin32Error());
        }

        public static int CallNextHook(IntPtr hhk, int nCode, int wParam, IntPtr lParam)
        {
            return CallNextHookEx(hhk, nCode, wParam, lParam);
        }

        public static IntPtr UnregisterWindowsHook(IntPtr hhk)
        {
            return UnhookWindowsHookEx(hhk);
        }
    }
}
